package com.shareware.common.delegate

import android.content.Context
import com.shareware.common.getContextGlobal
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty

/**
 * desc: 功能描述
 * sp 扩展类
 * email: mobiledeveloper@qq.com
 */
class Preference<T> constructor(
    private val name: String, private val default: T,
    private val prefName: String = "default",
) : ReadWriteProperty<Any?, T> {

    private val preference by lazy {
        getContextGlobal().getSharedPreferences(prefName, Context.MODE_PRIVATE)
    }

    override fun getValue(thisRef: Any?, property: KProperty<*>): T {
        return findPreference(findProperName(property))
    }

    private fun findProperName(property: KProperty<*>) = name.ifEmpty { property.name }

    @Suppress("IMPLICIT_CAST_TO_ANY", "UNCHECKED_CAST")
    private fun findPreference(key: String): T {
        return when (default) {
            is String -> preference.getString(key, default).orEmpty()
            is Int -> preference.getInt(key, default)
            is Boolean -> preference.getBoolean(key, default)
            is Long -> preference.getLong(key, default)
            is Float -> preference.getFloat(key, default)
            is Set<*> -> preference.getStringSet(key, default as Set<String>).orEmpty()
            else -> throw IllegalArgumentException("unsupported type")
        } as T
    }

    override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
        putPreference(findProperName(property), value)
    }

    @Suppress("UNCHECKED_CAST")
    private fun putPreference(key: String, value: T) {
        with(preference.edit()) {
            when (value) {
                is String -> putString(key, value)
                is Int -> putInt(key, value)
                is Boolean -> putBoolean(key, value)
                is Long -> putLong(key, value)
                is Float -> putFloat(key, value)
                is MutableSet<*> -> putStringSet(key, value as Set<String>)
                else -> throw IllegalArgumentException("unsupported type")
            }.apply()
        }
    }
}